#region Using Statements
using System;
using System.IO;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
#endregion

namespace SkyBurner
{
    #region BoundingBoxEx class
    public class BoundingBoxEx
    {
        protected Vector3 m_Min;
        protected Vector3 m_Max;
        protected Vector3[] m_Vertices = new Vector3[8];
        protected Vector3[] m_VerticesXForm = new Vector3[8];

        public Vector3 Min
        {
            get { return m_Min; }
            set
            {
                m_Min = value;
                ComputeVertices();
            }
        }

        public Vector3 Max
        {
            get { return m_Max; }
            set
            {
                m_Max = value;
                ComputeVertices();
            }
        }

        public BoundingBoxEx()
        {
            m_Min = Vector3.Zero;
            m_Max = Vector3.Zero;
        }

        public BoundingBoxEx(Vector3 pMin, Vector3 pMax)
        {
            m_Min = pMin;
            m_Max = pMax;
            ComputeVertices();
        }

        protected void ComputeVertices()
        {
            // bottom of the box
            m_Vertices[0].X = m_Min.X; m_Vertices[0].Y = m_Min.Y; m_Vertices[0].Z = m_Min.Z;
            m_Vertices[1].X = m_Min.X; m_Vertices[1].Y = m_Min.Y; m_Vertices[1].Z = m_Max.Z;
            m_Vertices[2].X = m_Max.X; m_Vertices[2].Y = m_Min.Y; m_Vertices[2].Z = m_Max.Z;
            m_Vertices[3].X = m_Max.X; m_Vertices[3].Y = m_Min.Y; m_Vertices[3].Z = m_Min.Z;

            // top of the box
            m_Vertices[4].X = m_Min.X; m_Vertices[4].Y = m_Max.Y; m_Vertices[4].Z = m_Min.Z;
            m_Vertices[5].X = m_Min.X; m_Vertices[5].Y = m_Max.Y; m_Vertices[5].Z = m_Max.Z;
            m_Vertices[6].X = m_Max.X; m_Vertices[6].Y = m_Max.Y; m_Vertices[6].Z = m_Max.Z;
            m_Vertices[7].X = m_Max.X; m_Vertices[7].Y = m_Max.Y; m_Vertices[7].Z = m_Min.Z;
        }

        public void Transform(Matrix pXFormMatrix)
        {
            for (int i = 0; i < 8; i++)
            {
                m_VerticesXForm[i] = Vector3.Transform(m_Vertices[i], pXFormMatrix);

                if (i == 0)
                {
                    m_Min = m_VerticesXForm[i];
                    m_Max = m_VerticesXForm[i];
                }
                else
                {
                    m_Min = Vector3.Min(m_Min, m_VerticesXForm[i]);
                    m_Max = Vector3.Max(m_Max, m_VerticesXForm[i]);
                }
            }
        }

        public bool Intersect(BoundingBoxEx pBoundingBoxEx)
        {
            // AABB separating axis check...
            bool bOverlapOnX = ((m_Max.X - pBoundingBoxEx.m_Min.X) > 0.0f) && ((pBoundingBoxEx.m_Max.X - m_Min.X) > 0.0f);
            bool bOverlapOnY = ((m_Max.Y - pBoundingBoxEx.m_Min.Y) > 0.0f) && ((pBoundingBoxEx.m_Max.Y - m_Min.Y) > 0.0f);
            bool bOverlapOnZ = ((m_Max.Z - pBoundingBoxEx.m_Min.Z) > 0.0f) && ((pBoundingBoxEx.m_Max.Z - m_Min.Z) > 0.0f);

            return bOverlapOnX && bOverlapOnY && bOverlapOnZ;
        }

        public bool Intersect(BoundingSphere pBoundingSphere)
        {
            float fDist = 0.0f;
            if (pBoundingSphere.Center.X < m_Min.X)
                fDist += (m_Min.X - pBoundingSphere.Center.X) * (m_Min.X - pBoundingSphere.Center.X);
            else if (pBoundingSphere.Center.X > m_Max.X)
                fDist += (pBoundingSphere.Center.X - m_Max.X) * (pBoundingSphere.Center.X - m_Max.X);

            if (pBoundingSphere.Center.Y < m_Min.Y)
                fDist += (m_Min.Y - pBoundingSphere.Center.Y) * (m_Min.Y - pBoundingSphere.Center.Y);
            else if (pBoundingSphere.Center.Y > m_Max.Y)
                fDist += (pBoundingSphere.Center.Y - m_Max.Y) * (pBoundingSphere.Center.Y - m_Max.Y);

            if (pBoundingSphere.Center.Z < m_Min.Z)
                fDist += (m_Min.Z - pBoundingSphere.Center.Z) * (m_Min.Z - pBoundingSphere.Center.Z);
            else if (pBoundingSphere.Center.Z > m_Max.Z)
                fDist += (pBoundingSphere.Center.Z - m_Max.Z) * (pBoundingSphere.Center.Z - m_Max.Z);

            return fDist < (pBoundingSphere.Radius * pBoundingSphere.Radius);
        }
    }
    #endregion
}
